/*
 * Copyright (C) 2019. Uber Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.lzy.okgo.harmony.autodispose;


import com.lzy.okgo.harmony.autodispose.harmony.internal.AutoDisposeHarmonyUtil;
import com.lzy.okgo.harmony.autodispose.harmony.internal.MainThreadDisposable;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.annotations.Nullable;
import io.reactivex.subjects.BehaviorSubject;
import ohos.aafwk.ability.ILifecycleObserver;
import ohos.aafwk.ability.Lifecycle;
import ohos.aafwk.ability.LifecycleStateObserver;
import ohos.aafwk.content.Intent;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;

import static ohos.aafwk.ability.Lifecycle.Event.*;

class LifecycleEventsObservable extends Observable<Lifecycle.Event> implements ILifecycleObserver {
    private final Lifecycle lifecycle;
    private final BehaviorSubject<Lifecycle.Event> eventsObservable = BehaviorSubject.create();

    @SuppressWarnings("CheckReturnValue")
    LifecycleEventsObservable(Lifecycle lifecycle) {
        this.lifecycle = lifecycle;
        lifecycle.addObserver(this);
    }

    Lifecycle.Event getValue() {
        return eventsObservable.getValue();
    }

    /**
     * Backfill if already created for boundary checking. We do a trick here for corresponding events
     * where we pretend something is created upon initialized state so that it assumes the
     * corresponding event is DESTROY.
     */
    void backfillEvents() {
        @Nullable Lifecycle.Event correspondingEvent;
        switch (lifecycle.getLifecycleState()) {
            case ON_START:
                correspondingEvent = ON_ACTIVE;
                break;
            case ON_ACTIVE:
                correspondingEvent = ON_INACTIVE;
                break;
            case ON_BACKGROUND:
            case ON_STOP:
            default:
                correspondingEvent = ON_BACKGROUND;
        }
        eventsObservable.onNext(correspondingEvent);
    }

    @Override
    protected void subscribeActual(Observer<? super Lifecycle.Event> observer) {
        AutoDisposeLifecycleObserver lifecycleObserver =
                new AutoDisposeLifecycleObserver(lifecycle, observer, eventsObservable);
        observer.onSubscribe(lifecycleObserver);
//    lifecycleObserver.onStateChange(lifecycle,lifecycle.getLifecycleState());
        if (!AutoDisposeHarmonyUtil.isMainThread()) {
            observer.onError(
                    new IllegalStateException("Lifecycles can only be bound to on the main thread!"));
            return;
        }
        lifecycle.addObserver(lifecycleObserver);
//    lifecycle.dispatchLifecycle(lifecycle.getLifecycleState());
        if (lifecycleObserver.isDisposed()) {
            lifecycle.removeObserver(lifecycleObserver);
        }
    }

    static final class AutoDisposeLifecycleObserver extends MainThreadDisposable implements ILifecycleObserver, LifecycleStateObserver {
        private final Lifecycle lifecycle;
        private final Observer<? super Lifecycle.Event> observer;
        private final BehaviorSubject<Lifecycle.Event> eventsObservable;
        HiLogLabel hiLogLabel = new HiLogLabel(HiLog.LOG_APP, 56789, "LifecycleEventsObservable");

        AutoDisposeLifecycleObserver(
                Lifecycle lifecycle,
                Observer<? super Lifecycle.Event> observer,
                BehaviorSubject<Lifecycle.Event> eventsObservable) {
            this.lifecycle = lifecycle;
            this.observer = observer;
            this.eventsObservable = eventsObservable;
        }

        @Override
        protected void onDispose() {
            lifecycle.removeObserver(this);
        }


        @Override
        public void onStateChanged(Lifecycle.Event event, Intent intent) {
            HiLog.info(hiLogLabel, "onStateChange" + event);
            if (!isDisposed()) {
                if (!(event == ON_START && eventsObservable.getValue() == event)) {
                    // Due to the INITIALIZED->ON_CREATE mapping trick we do in backfill(),
                    // we fire this conditionally to avoid duplicate CREATE events.
                    eventsObservable.onNext(event);
                }
                observer.onNext(event);
            }
        }
    }
}
